package vek.XML.Parsers;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.util.ArrayList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import util.FileGetter;
import vek.XML.parsedObjects.ParsedObjectInterface;
import vek.XML.parsedObjects.ParsedMap;

/**
 * This class contains functionality that will parse various XML-files associated with the program.
 * 
 * @author Christian, Michal og Jakob (Hold 1, gruppe 2)
 * inspiration fra: http://www.javaworld.com/jw-03-2000/jw-03-xmlsax.html?page=1
 * og: http://www.totheriver.com/learn/xml/xmltutorial.html#5.4
 */

public class XMLParserMain {
    
    /**
     * Determines which parser to use based on the XML-files filename and creates a XMLParser object.
     * @param s The URL of the XML-file
     * @return The XMLParser object that should be used for parsing the XML-file given as argument. 
     */
    private static NonAbstractXMLParserInterface selectParser(String s)
    {
        
        if( s.substring( s.lastIndexOf(System.getProperty("file.separator")) + 1, s.lastIndexOf("_" )).startsWith("restaurants"))
        {
            XMLParserRestaurants parserHandler2 = new XMLParserRestaurants();
            return parserHandler2;
        }
        else if( s.substring( s.lastIndexOf(System.getProperty("file.separator")) + 1, s.lastIndexOf("_" )).startsWith("museums"))
        {
            XMLParserMuseums parserHandler2 = new XMLParserMuseums();
            return parserHandler2;
        }
        else
        {
            System.err.println( s );
            assert false : "Error unknown xml " + s + " parsed";
            return null;
        }
    }
    
    /**
     * Parse an XML-file by selecting a parser to use and subsequently using it.
     * Finally an arraylist containing the ParsedObjects that the XML-file contained data for are returned.
     * @param s The path of the XML-file
     * @return an arraylist containing the parsed objects
     */
    public static ArrayList<ParsedObjectInterface> parseXMLAndReturnParsedObjects(String s)
    {
        XMLReader parser = null;
    
        try { parser = XMLReaderFactory.createXMLReader(); } 
        catch (SAXException e) { System.err.println(e.getMessage()); }
    
        NonAbstractXMLParserInterface parserHandler = selectParser(s);

   
        parser.setContentHandler(parserHandler); // set the type of parser for this file
        try{ parser.parse(new InputSource(FileGetter.getFileAsFileInputStreamAbsolutePath(s))); }
        catch (Exception e) { System.err.println("error parsing file: " + parser.getContentHandler().toString()); }
    
        
        ArrayList<ParsedObjectInterface> returnedAl = parserHandler.getParsedObjects();
        
        return returnedAl;
    }
    
    /**
     * Parses a XML-file containing data about the map used as a background in the program and returns a ParsedMap object.
     * @param s The path of the XML-file
     * @return a ParsedMap object.
     */
    public static ParsedMap parseXMLAndReturnParsedMap(String s)
    {
        XMLReader parser = null;
    
        try { parser = XMLReaderFactory.createXMLReader(); } 
        catch (SAXException e) { System.err.println(e.getMessage()); }
    
        XMLParser_MapParser parserHandler = new XMLParser_MapParser();

   
        parser.setContentHandler(parserHandler); // set the type of parser for this file
        try{ parser.parse(new InputSource(FileGetter.getFileAsFileInputStream(s))); }
        catch (Exception e) { System.err.println("error parsing file"); }
    
        return parserHandler.getParsedMap();
    }
   
    /**
     * Parses all the XML-files in a directory and returns an arraylist containing arraylists containing the ParsedObjects (essentially a 2D array of variable size).
     * @param s path of the directory containing the XML-files to be parsed
     * @return an arraylist containing array lists containing ParsedObjects. This is essentially a 2D array of variable size.
     */
    public static ArrayList<ArrayList<ParsedObjectInterface>> parseAllXMLFilesInDirectory(String s)
    {
        ArrayList<String> xmlFiles = FileGetter.getXMLFilesInDirectoryAsArrayList(s);
        ArrayList<ArrayList<ParsedObjectInterface>> allObjects = new ArrayList<ArrayList<ParsedObjectInterface>>();
        
        for(int i = 0; i < xmlFiles.size(); i++)
        {
            System.out.println("parsing: " + xmlFiles.get(i));
            ArrayList<ParsedObjectInterface> parsedObjects = parseXMLAndReturnParsedObjects( xmlFiles.get(i) );
            if(parsedObjects != null)
            {
                allObjects.add( parsedObjects );
            }
                
        }
        
        return allObjects;
    }
    
    /**
     * Parses the XML-file cointaining date used by the update functionality.
     * @param s the path to the XML-file containing the settings for the Update functionlality.
     * @return 
     */
    public static ArrayList<String> parseUpdateXML(String s)
    {
        BufferedInputStream updateXMLStream = FileGetter.getFileAsInputStreamFromURL(s);
        
        XMLParserUpdate handler = new XMLParserUpdate();
        
        XMLReader parser = null;
    
        try { parser = XMLReaderFactory.createXMLReader(); } 
        catch (SAXException e) { System.err.println(e.getMessage()); }
        
        parser.setContentHandler(handler);
        
         try{ parser.parse(new InputSource(updateXMLStream)); }
         catch (Exception e) 
         { 
            System.err.println("error parsing update file");
            return null; 
         }
        
        return handler.getListOfXMLFiles();
         
    }
    
    /**
     * Parses the XML-file containing the settings data.
     * @param s the path of the XML-file containtaining the settings data.
     */
    public static void parseSettings(String s)
    {
        FileInputStream updateXMLStream = FileGetter.getFileAsFileInputStream(s);
        
        XMLParserSettings handler = new XMLParserSettings();
        
        XMLReader parser = null;
    
        try { parser = XMLReaderFactory.createXMLReader(); } 
        catch (SAXException e) { System.err.println(e.getMessage()); }
        
        parser.setContentHandler(handler);
        
         try{ parser.parse(new InputSource(updateXMLStream)); }
         catch (Exception e) { System.err.println("error parsing settings file"); }
        
        // save settings
        
    }
    
}

